package com.fulihui.wgj.service.template;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.fulihui.common.builder.rpc.RpcResultBuilder;
import com.fulihui.common.enums.SendLogStatusEnum;
import com.fulihui.common.enums.TemplateLogTypeEnum;
import com.fulihui.common.enums.TemplateStatusEnum;
import com.fulihui.common.error.Errors;
import com.fulihui.common.error.InvokeServiceException;
import com.fulihui.common.result.rpc.BaseResult;
import com.fulihui.common.util.ConditionValidator;
import com.fulihui.common.util.PlatformUtil;
import com.fulihui.weixinsdk.WeixinSDK;
import com.fulihui.weixinsdk.model.TemplateItem;
import com.fulihui.weixinsdk.request.template.TemplateSendRequest;
import com.fulihui.weixinsdk.result.template.TemplateSendResult;
import com.fulihui.weixinsdk.result.user.UserInfoGetResult;
import com.fulihui.wgj.biz.SendHistoryUserBiz;
import com.fulihui.wgj.biz.SendTemplateMsgBiz;
import com.fulihui.wgj.biz.WeiXinSdkBiz;
import com.fulihui.wgj.biz.common.util.NickNameUtil;
import com.fulihui.wgj.biz.common.util.TemplateRenderUtil;
import com.fulihui.wgj.dal.mybatis.domain.WxSendTemplateLog;
import com.fulihui.wgj.dal.mybatis.domain.WxTemplate;
import com.fulihui.wgj.dal.mybatis.repository.WxSendTemplateLogRepository;
import com.fulihui.wgj.dal.mybatis.repository.WxTemplateRepository;
import com.fulihui.wgj.facade.request.template.LocalTemplateSendRequest;
import com.fulihui.wgj.facade.request.template.SinglePreviewRequest;
import com.fulihui.wgj.facade.request.wxuser.WxHistorySendUserSaveRequest;
import com.fulihui.wgj.facade.service.template.WxLocalTemplateService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author: Levon
 * @date: 2018-07-26 14:24
 */
@Component
@Service(interfaceClass = WxLocalTemplateService.class, version = "1.0.0")
public class WxLocalTemplateServiceImpl implements WxLocalTemplateService {

    private final static Logger LOGGER = LoggerFactory.getLogger(WxLocalTemplateServiceImpl.class);

    @Autowired
    private PlatformUtil platformUtil;

    @Autowired
    private WeiXinSdkBiz weiXinSdkBiz;

    @Autowired
    private WeixinSDK weixinSDK;

    @Autowired
    private SendHistoryUserBiz sendHistoryUserBiz;

    @Autowired
    WxTemplateRepository wxTemplateRepository;

    @Autowired
    WxSendTemplateLogRepository wxSendTemplateLogRepository;

    @Autowired
    SendTemplateMsgBiz sendTemplateMsgBiz;

    @Override
    public BaseResult singlePreview(SinglePreviewRequest request) throws InvokeServiceException {

        ConditionValidator.validate(request);
        String accessToken = platformUtil.get(request.getAppId());

        if (StringUtils.isNotBlank(accessToken)) {
            TemplateSendRequest templateSendRequest = new TemplateSendRequest();
            templateSendRequest.setAccess_token(accessToken);
            templateSendRequest.setTemplate_id(request.getTemplateId());
            templateSendRequest.setTouser(request.getOpenId());
            templateSendRequest.setUrl(request.getTemplateUrl());
            if (request.getMiniApp() && request.getMiniprogram() != null) {
                templateSendRequest.setMiniprogram(request.getMiniprogram());
            }
            Map<String, TemplateItem> data = JSON.parseObject(request.getTemplateContent(), new TypeReference<Map<String, TemplateItem>>() {
            });

            UserInfoGetResult userDetail = weiXinSdkBiz.getUserDetail(request.getAppId(), request.getOpenId());
            if (userDetail != null && userDetail.getUserInfo() != null) {
                String nickname = userDetail.getUserInfo().getNickname();
                if (StringUtils.isNotBlank(nickname)) {
                    NickNameUtil.replaceNickname(data, nickname);
                }
            }
            templateSendRequest.setData(data);
            TemplateSendResult sendResult = weixinSDK.invokeService(templateSendRequest);
            if (sendResult.isSuccess()) {
                WxHistorySendUserSaveRequest saveRequest = new WxHistorySendUserSaveRequest();
                saveRequest.setOpenid(request.getOpenId());
                saveRequest.setAppId(request.getAppId());
                sendHistoryUserBiz.saveHistorySendUser(saveRequest);
            }
            return RpcResultBuilder.succ();
        }
        return RpcResultBuilder.fail(500, "send single template message is fail");
    }

    @Override
    public BaseResult sendTemplateMsgLocal(LocalTemplateSendRequest request) throws InvokeServiceException {
        LOGGER.info("rpc sendTemplateMsgLocal start, request openIds.size={}, appId={},templateId={}," +
                        "templateContent={},templateUrl={},miniApp={},miniAppId={},miniAppUrl={},"
                , request.getOpenIds().size(), request.getAppId(), request.getTemplateId(), request.getTemplateContent()
                , request.getTemplateUrl(), request.getMiniApp(), request.getMiniAppId(), request.getMiniAppUrl());
        ConditionValidator.validate(request);

        // 先判断模板是否已失效
        String templateId = request.getTemplateId();
        WxTemplate wxTemplateQuery = new WxTemplate();
        wxTemplateQuery.setTemplateId(templateId);
        WxTemplate wxTemplate = wxTemplateRepository.queryOne(wxTemplateQuery);
        if (Objects.isNull(wxTemplate) || TemplateStatusEnum.valid.getValue() != wxTemplate.getStatus().longValue()) {
            return RpcResultBuilder.fail(Errors.WxTemplateError.THIS_TEMPLATE_IS_NOT_VALID);
        }

        // 推送人数为0 不进行推送
        List<String> openIds = request.getOpenIds();
        if (CollectionUtils.isEmpty(openIds)) {
            return RpcResultBuilder.fail(Errors.WxTemplateLogError.THE_CURRENT_APP_PUSHES_RECORD_EMPTY);
        }

        int recordCount = openIds.size();
        LOGGER.info("sendTemplateMsgLocal recordCount:{}", recordCount);

        // 插入发送记录表
        WxSendTemplateLog templateLog = insertTemplateLog(request, TemplateLogTypeEnum.LOCAL.getValue(), recordCount);
        if (Objects.isNull(templateLog) || Objects.isNull(templateLog.getId())) {
            LOGGER.info("SendTemplateMsgService sendTemplateMsg, templateLogId is null!!!");
            return RpcResultBuilder.fail(Errors.WxTemplateLogError.TEMPLATE_LOG_RECORD_INSERT_ERROR);
        }

        LOGGER.info("WxLocalTemplateService, send local now!");
        sendTemplateMsgBiz.sendTemplateMsg4Local(openIds, templateLog);

        return RpcResultBuilder.succ();
    }

    /**
     * 插入消息发送记录表
     *
     * @param condition
     * @param logType     设置模板记录类型{@link com.fulihui.common.enums.TemplateLogTypeEnum}
     * @param recordCount
     * @return
     */
    private WxSendTemplateLog insertTemplateLog(LocalTemplateSendRequest condition, int logType, Integer recordCount) {
        // 模板发送数据
        String templateContent = condition.getTemplateContent();
        Map<String, TemplateItem> data = JSON.parseObject(templateContent,
                new TypeReference<Map<String, TemplateItem>>() {
                });

        WxSendTemplateLog templateLog = new WxSendTemplateLog();
        templateLog.setTemplateLogType(logType);
        templateLog.setAppId(condition.getAppId());
        if (condition.getMiniApp() && StringUtils.isNotBlank(condition.getMiniAppUrl())) {
            templateLog.setMiniProgramUrl(condition.getMiniAppUrl());
        }
        templateLog.setSendStatus(SendLogStatusEnum.pushing.getCode());

        templateLog.setAllTotal(recordCount);
        templateLog.setFailTotal(0);
        templateLog.setSuccessTotal(0);
        templateLog.setSendStartTime(new Date());
        templateLog.setSendEndTime(null);
        templateLog.setTemplateContent(renderTemplate(data, condition.getTemplateId()));
        templateLog.setTemplateData(templateContent);
        templateLog.setJumpUrl(condition.getTemplateUrl());
        templateLog.setTemplateId(condition.getTemplateId());
        wxSendTemplateLogRepository.saveSelective(templateLog);
        LOGGER.info("insertTemplateLog:{}", templateLog);
        return templateLog;
    }

    /**
     * 渲染模板内容
     *
     * @param data
     * @param templateId 模板ID
     * @return
     */
    private String renderTemplate(Map<String, TemplateItem> data, String templateId) {
        WxTemplate wxTemplateQuery = new WxTemplate();
        wxTemplateQuery.setTemplateId(templateId);
        List<WxTemplate> templateList = wxTemplateRepository.queryByWhere(wxTemplateQuery);
        if (!CollectionUtils.isEmpty(templateList)) {
            WxTemplate wxTemplate = templateList.get(0);
            if (Objects.nonNull(wxTemplate)) {
                return TemplateRenderUtil.render(data, wxTemplate);
            }
        }
        return null;
    }
}
